#include <iostream>
using namespace std;

struct Foo {
    int x;
};

template<class T>
class Pointer {
    T* thePtr;
public:
    Pointer(T* p) {
        thePtr = p;
    }
    ~Pointer() {
        cout << "the delete\n";
        delete thePtr;
    }
    T* operator->() {
        cout << "Pointer<T>::operator->\n";
        return thePtr;
    }
    T& operator*() {
        return *thePtr;
    }
};

template<class T>
class Wrapper {
    Pointer<T> thePtr;
public:
    Wrapper(const Pointer<T>& p) : thePtr(p) { }
    Pointer<T> operator->() {
        cout << "Wrapper<T>::operator->\n";
        return thePtr;
    }
};

int main() {
    Pointer<int> p(new int(7));
    cout << *p << endl;

    Foo* f = new Foo;
    f->x = 10;
    Pointer<Foo> p2(f);
    cout << p2->x << endl;

    Wrapper<Foo> p3(p2);
    cout << p3->x << endl;
}
